-- description: 脏读 Dirty read
-- date: 2024-03-18 22:57
-- author: liyf
-- database: study
-- table: account
-- comment: 一个事务读取并且操作了另一个事务尚未提交的数据，如果另一个事务回滚，则读取到的数据是无效的。


-- 测试数据
drop table if exists account;
create table account(
                        id int primary key AUTO_INCREMENT comment 'ID',
                        name varchar(10) comment '姓名',
                        money double(10,2) comment '余额'
) comment '账户表';
insert into account(name, money) VALUES ('张三',2000), ('李四',2000);

-- 脏读演示
-- 打开两个命令行窗口执行
-- 1. 修改会话1默认隔离级别
set session TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 2. 在会话1中执行查询
select * from account;
# +----+------+---------+
# | id | name | money   |
# +----+------+---------+
# |  1 | 张三 | 2000.00 |
# |  2 | 李四 | 2000.00 |
# +----+------+---------+
# 2 rows in set (0.00 sec)

-- 3. 在会话2中开始起始
begin;

-- 4. 在会话2中执行更新语句
update account set money = 1000 where id = 1;

-- 5. 再次回到会话1中执行查询语句
select * from account;
# +----+------+---------+
# | id | name | money   |
# +----+------+---------+
# |  1 | 张三 | 1000.00 |
# |  2 | 李四 | 2000.00 |
# +----+------+---------+
# 2 rows in set (0.00 sec)

-- 6. 回到会话2中执行回滚操作
rollback;

-- 7. 再次回到会话1中执行查询语句 （发现数据又恢复成正常了）
select * from account;
# +----+------+---------+
# | id | name | money   |
# +----+------+---------+
# |  1 | 张三 | 2000.00 |
# |  2 | 李四 | 2000.00 |
# +----+------+---------+
# 2 rows in set (0.00 sec)


-- 解决脏读演示

-- 打开两个命令行窗口执行
-- 1. 修改会话1默认隔离级别
set session TRANSACTION ISOLATION LEVEL READ COMMITTED;

-- 2. 在会话1中执行查询
select * from account;
# +----+------+---------+
# | id | name | money   |
# +----+------+---------+
# |  1 | 张三 | 2000.00 |
# |  2 | 李四 | 2000.00 |
# +----+------+---------+
# 2 rows in set (0.00 sec)

-- 3. 在会话2中开始起始
begin;

-- 4. 在会话2中执行更新语句
update account set money = 1000 where id = 1;

-- 5. 再次回到会话1中执行查询语句
select * from account;
# +----+------+---------+
# | id | name | money   |
# +----+------+---------+
# |  1 | 张三 | 2000.00 |
# |  2 | 李四 | 2000.00 |
# +----+------+---------+
# 2 rows in set (0.00 sec)

-- 6. 回到会话2中执行回滚操作
rollback;

-- 7. 再次回到会话1中执行查询语句 （发现数据又恢复成正常了）
select * from account;
# +----+------+---------+
# | id | name | money   |
# +----+------+---------+
# |  1 | 张三 | 2000.00 |
# |  2 | 李四 | 2000.00 |
# +----+------+---------+
# 2 rows in set (0.00 sec)